Imports System
Imports System.IO
Imports System.Security.AccessControl
Imports Microsoft.Win32
'Imports IWshRuntimeLibrary

Module modMain
    Private Const IIS_SERVICENAME As String = "W3SVC"
    Private Const SAD_SERVICENAME As String = "SQLAutoDocSVC"

    Public Sub Main()
        Try
            '---Get directory entries from registry
            Dim oKey As RegistryKey = Registry.LocalMachine
            Dim oSADKey As RegistryKey = oKey.OpenSubKey("SOFTWARE\jlion.com\SAD")

            Dim sInterfaceDir As String = TrimQuotes(oSADKey.GetValue("Interfacedir"))
            Dim sServiceDir As String = TrimQuotes(oSADKey.GetValue("ServiceDir"))
            Dim sSite As String = TrimQuotes(oSADKey.GetValue("Site"))
            Dim sVirtualDir As String = TrimQuotes(oSADKey.GetValue("VirtualDir"))

            '---Add ASPNET with full ownership to app_data folder
            Dim sAPPDATADirectory As String = sInterfaceDir & "App_Data"
            Dim sASPAccount As String = My.Computer.Name & "\" & "ASPNET"

            RemoveInheritanceDirectorySecurity( _
                sAPPDATADirectory)

            AddFullControlToDirectory( _
                sAPPDATADirectory, _
                sASPAccount)

            AddFullControlToDirectory( _
                sAPPDATADirectory, _
                "builtin\Users")

            Dim sDB As String = sAPPDATADirectory & "\metadata.mdf"

            AddFullControlToFile( _
                sDB, _
                sASPAccount)

            AddFullControlToFile( _
                sDB, _
                "builtin\Users")

            Dim sLog As String = sAPPDATADirectory & "\metadata_log.ldf"

            AddFullControlToFile( _
                sLog, _
                sASPAccount)

            AddFullControlToFile( _
                sLog, _
                "builtin\Users")

            '---Content directory permisssions
            Dim sContentDirectory As String = sInterfaceDir & "content"

            AddFullControlToFile( _
                sContentDirectory, _
                sASPAccount)

            AddFullControlToFile( _
                sContentDirectory, _
                "builtin\Users")

            '---Temp directory permisssions
            Dim sTempDirectory As String = sInterfaceDir & "content\temp"

            AddFullControlToFile( _
                sTempDirectory, _
                sASPAccount)

            AddFullControlToFile( _
                sTempDirectory, _
                "builtin\Users")


            '---Restart IIS
            RestartService(IIS_SERVICENAME)

            '---Update service config file.

            '---Start service
            'StartService(SAD_SERVICENAME)

            Try
                Dim oSpecialFolder As New SpecialFolder
                Dim oShortCut As New CreateInternetShortcut

                Dim sURL As String = "http://" & My.Computer.Name & "/" & sVirtualDir & "/"

                '---Create shortcut to web app on desktop
                Dim sDesktopPath As String = oSpecialFolder.GetSpecialFolderLocation(SpecialFolder.CSIDL.COMMON_DESKTOPDIRECTORY)
                oShortCut.CreateShortcut(sDesktopPath & "SQLAutoDoc", sURL)

                '---Create shortcut to web app in program files
                Dim sProgramFilesPath As String = oSpecialFolder.GetSpecialFolderLocation(SpecialFolder.CSIDL.COMMON_PROGRAMS)
                Dim sCompanyDir As String = sProgramFilesPath & "\jlion.com"
                If Not Directory.Exists(sCompanyDir) Then
                    Directory.CreateDirectory(sCompanyDir)
                End If

                Dim sProgramDir As String = sCompanyDir & "\sqlautodoc"
                If Not Directory.Exists(sProgramDir) Then
                    Directory.CreateDirectory(sProgramDir)
                End If

                oShortCut.CreateShortcut(sDesktopPath & "\SQLAutoDoc", sURL)
                oShortCut.CreateShortcut(sProgramDir & "\SQLAutoDoc", sURL)
            Catch oEX As Exception
                MessageBox.Show(oEX.Message & vbCrLf & oEX.StackTrace.ToString)
            End Try
        Catch oEX As Exception
            MessageBox.Show(oEX.Message & vbCrLf & oEX.StackTrace.ToString)
        End Try
    End Sub

    Private Sub AddFullControlToDirectory( _
            ByVal sDirectoryName As String, _
            ByVal sAccount As String)

        AddDirectorySecurity( _
            sDirectoryName, _
            sAccount, _
            FileSystemRights.Modify, _
            AccessControlType.Allow)

        AddDirectorySecurity( _
            sDirectoryName, _
            sAccount, _
            FileSystemRights.ReadAndExecute, _
            AccessControlType.Allow)

        AddDirectorySecurity( _
            sDirectoryName, _
            sAccount, _
            FileSystemRights.ListDirectory, _
            AccessControlType.Allow)

        AddDirectorySecurity( _
            sDirectoryName, _
            sAccount, _
            FileSystemRights.Read, _
            AccessControlType.Allow)

        AddDirectorySecurity( _
            sDirectoryName, _
            sAccount, _
            FileSystemRights.Write, _
            AccessControlType.Allow)

        AddDirectorySecurity( _
            sDirectoryName, _
            sAccount, _
            FileSystemRights.FullControl, _
            AccessControlType.Allow)
    End Sub

    Private Sub AddFullControlToFile( _
        ByVal sFileName As String, _
        ByVal sAccount As String)

        AddFileSecurity( _
            sFileName, _
            sAccount, _
            FileSystemRights.Modify, _
            AccessControlType.Allow)

        AddFileSecurity( _
            sFileName, _
            sAccount, _
            FileSystemRights.ReadAndExecute, _
            AccessControlType.Allow)

        AddFileSecurity( _
            sFileName, _
            sAccount, _
            FileSystemRights.ListDirectory, _
            AccessControlType.Allow)

        AddFileSecurity( _
            sFileName, _
            sAccount, _
            FileSystemRights.Read, _
            AccessControlType.Allow)

        AddFileSecurity( _
            sFileName, _
            sAccount, _
            FileSystemRights.Write, _
            AccessControlType.Allow)

        AddFileSecurity( _
            sFileName, _
            sAccount, _
            FileSystemRights.FullControl, _
            AccessControlType.Allow)
    End Sub

    '   Adds an ACL entry on the specified file for the specified account.
    '   From: http://msdn2.microsoft.com/en-us/library/system.security.accesscontrol.filesystemrights.aspx
    Private Sub AddDirectorySecurity( _
                ByVal sDirectoryName As String, _
                ByVal sAccount As String, _
                ByVal oRights As FileSystemRights, _
                ByVal oControlType As AccessControlType)

        Dim oDir As DirectorySecurity = Directory.GetAccessControl(sDirectoryName)
        oDir.AddAccessRule(New FileSystemAccessRule(sAccount, FileSystemRights.FullControl, AccessControlType.Allow))
        Directory.SetAccessControl(sDirectoryName, oDir)
    End Sub

    Private Sub AddFileSecurity( _
            ByVal sFileName As String, _
            ByVal sAccount As String, _
            ByVal oRights As FileSystemRights, _
            ByVal oControlType As AccessControlType)

        Dim oFile As FileSecurity = File.GetAccessControl(sFileName)
        oFile.AddAccessRule(New FileSystemAccessRule(sAccount, FileSystemRights.FullControl, AccessControlType.Allow))
        File.SetAccessControl(sFileName, oFile)
    End Sub

    Private Sub RemoveInheritanceDirectorySecurity( _
            ByVal sFileName As String)

        ' Get a FileSecurity object that represents the 
        ' current security settings.
        Dim oDirInfo As New DirectoryInfo(sFileName)
        Dim fSecurity As DirectorySecurity = oDirInfo.GetAccessControl(AccessControlSections.All)

        fSecurity.SetAccessRuleProtection(True, False)
        oDirInfo.SetAccessControl(fSecurity)
    End Sub

    Private Sub StartService(ByVal sServiceName As String)
        If GetServiceStatus(sServiceName) = ServiceProcess.ServiceControllerStatus.Stopped Then
            _StartService(sServiceName)

        ElseIf GetServiceStatus(sServiceName) = ServiceProcess.ServiceControllerStatus.Paused Then
            _ResumeService(sServiceName)
        End If
    End Sub

    Private Sub RestartService(ByVal sServiceName As String)
        If GetServiceStatus(sServiceName) = ServiceProcess.ServiceControllerStatus.Running Then
            _StopService(sServiceName)
            _StartService(sServiceName)

        ElseIf GetServiceStatus(sServiceName) = ServiceProcess.ServiceControllerStatus.Paused Then
            _ResumeService(sServiceName)

        ElseIf GetServiceStatus(sServiceName) = ServiceProcess.ServiceControllerStatus.Stopped Then
            _StartService(sServiceName)
        End If
    End Sub

    Private Sub _StopService(ByVal sServiceName As String)
        Dim oController As New _
           System.ServiceProcess.ServiceController(sServiceName, ".")

        oController.Stop()

        Dim sStartTime As Date = Now
        Do While oController.Status = ServiceProcess.ServiceControllerStatus.StopPending _
            AndAlso DateDiff(DateInterval.Second, sStartTime, Now) < 60

            oController.Refresh()
            Application.DoEvents()
        Loop
    End Sub

    Private Sub _StartService(ByVal sServiceName As String)
        Dim oController As New _
           System.ServiceProcess.ServiceController(sServiceName, ".")

        oController.Start()
    End Sub

    Private Sub _ResumeService(ByVal sServiceName As String)
        Dim oController As New _
           System.ServiceProcess.ServiceController(sServiceName, ".")

        oController.Continue()
    End Sub

    Private Sub _PauseService(ByVal sServiceName As String)
        Dim oController As New _
           System.ServiceProcess.ServiceController(sServiceName, ".")

        oController.Pause()
    End Sub

    Private Function GetServiceStatus(ByVal sServiceName As String) As ServiceProcess.ServiceControllerStatus
        Dim oController As New _
           System.ServiceProcess.ServiceController(sServiceName, ".")

        Return oController.Status
    End Function

    Private Function TrimQuotes(ByVal sValue As String) As String
        Dim sResult As String = sValue

        If sResult.Length > 2 Then
            If sResult.Substring(0, 1) = Chr(34) Then
                sResult = sResult.Substring(1, sResult.Length - 1)
            End If

            If sResult.Substring(sResult.Length - 1, 1) = Chr(34) Then
                sResult = sResult.Substring(0, sResult.Length - 1)
            End If
        End If

        Return sResult
    End Function
End Module
